
/**
 * 
 */
package cz.cuni.mff.abacs.burglar.logics.storage;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import cz.cuni.mff.abacs.burglar.logics.DataMap;
import cz.cuni.mff.abacs.burglar.logics.ExecutingMap;
import cz.cuni.mff.abacs.burglar.logics.objects.Room;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Agent;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.BeliefBase;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Burglar;
import cz.cuni.mff.abacs.burglar.logics.objects.agents.Guard;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Item;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Key;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Treasure;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Camera;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Container;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Door;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Floor;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Phone;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Position;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Switch;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Vender;


/** 
 * Static class, it's sole function is to loads a map from an XML file.
 * 
 * @author abacs
 *
 */
public class XMLLoader extends XMLBase {
	
	
	// -------------------------------------------------------------------------
	// constructors:
	
	
	/**
	 * Private constructor to prevent object creation.
	 */
	private XMLLoader() {  }
	
	
	// -------------------------------------------------------------------------
	// public functions:
	
	
	/**
	 * Loads
	 * 
	 * @param filename
	 * @return 
	 */
	public static ExecutingMap load(String filename) {
		Document doc = XMLBase.parseXmlFile(filename);
		return fillMap(doc);
	}
	
	
	/**
	 * Loads
	 * 
	 * @param filename
	 * @return 
	 */
	public static ExecutingMap load(InputStream inputStream) {
		Document doc = XMLBase.parseXmlStream(inputStream);
		return fillMap(doc);
	}
	
	
	/**
	 * Loads
	 * 
	 * @param filename
	 * @return 
	 */
	public static ExecutingMap fillMap(Document doc) {
		if(doc == null)
			return null;
		// get the root element
		Element root = doc.getDocumentElement();
		
		ExecutingMap ret = 
				new ExecutingMap(
						XMLLoader.getHighestID(root) + 1,
						XMLLoader.getRequiredTrapRoomCount(root)
				);
		
		ret.addRooms(XMLLoader.getRooms(root, ret));
		ret.addPositions(XMLLoader.getPositions(root, ret));
		ret.addAgents(XMLLoader.getAgents(root, ret));
		ret.addItems(XMLLoader.getItems(root, ret));
		
		ret.connectPositions();
		
		return ret;
	}
	
	
	// -------------------------------------------------------------------------
	// -------------------------------------------------------------------------
	// private implementation:
	
	
	/**
	 * Returns the highest id used in the map.
	 *  */
	private static int getHighestID(Element root) {
		int ret = 0;
		// get any element:
		NodeList nodes = root.getElementsByTagName("*");
		if(nodes == null || nodes.getLength() == 0)
			return ret;
		// find the largest id:
		for(int i = 0; i < nodes.getLength(); i++){
			Element element = (Element)nodes.item(i);
			int id = XMLBase.getIntAttrOrZero(element, STR_ID);
			if(id > ret)
				ret = id;
		}
		// return:
		return ret;
	}
	
	
	/**
	 * @return
	 *  */
	private static int getRequiredTrapRoomCount(Element root) {
		if(root.getNodeName().equals(STR_MAP)){
			return XMLBase.getIntAttrOrZero(root, STR_TRAP_COUNT);
		}
		
		// get a node list of selected elements:
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(
				node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName() == STR_MAP
			){
				// get the element
				Element pathElement = (Element)node;
				return XMLBase.getIntAttrOrZero(pathElement, STR_TRAP_COUNT);
			}
		}
		return 0;
	}
	
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Position> getPositions(Element root, DataMap map) {
		List<Position> ret = new ArrayList<Position>();
		ret.addAll(XMLLoader.getCameras(root, map));
		ret.addAll(XMLLoader.getContainers(root, map));
		ret.addAll(XMLLoader.getDoors(root, map));
		ret.addAll(XMLLoader.getFloors(root, map));
		ret.addAll(XMLLoader.getPhones(root, map));
		ret.addAll(XMLLoader.getSwitches(root, map));
		ret.addAll(XMLLoader.getVenders(root, map));
		return ret;
	}
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Agent> getAgents(Element root, DataMap map) {
		List<Agent> ret = new ArrayList<Agent>();
		ret.add(XMLLoader.getBurglar(root, map));
		ret.addAll(XMLLoader.getGuards(root, map));
		return ret;
	}
	
	
	/**
	 * 
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Item> getItems(Element root, DataMap map) {
		List<Item> ret = new ArrayList<Item>();
		ret.addAll(XMLLoader.getTreasures(root, map));
		ret.addAll(XMLLoader.getKeys(root, map));
		return ret;
	}
	
	
	// -------------------------------------------------------------------------
	// room:
	
	
	/**
	 * 
	 * Returns all the rooms in the map.
	 * 
	 * @param root
	 * @param nextFreeId 
	 * @return list of all rooms
	 */
	private static List<Room> getRooms(Element root, DataMap map) {
		List<Room> ret = new ArrayList<Room>();
		// get a node list of selected elements:
		NodeList rawList = root.getChildNodes();
		
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(
				node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_ROOM)
			){
				Room room = XMLLoader.getRoom((Element)node, map);
				ret.add(room);
			}
		}

		return ret;
	}
	
	
	/**
	 * Returns a single room in the map.
	 * 
	 * @param room_element
	 * @param nextFreeId 
	 * @return room
	 */
	private static Room getRoom(Element roomElement, DataMap map) {
		// get the attributes:
		int x      = XMLBase.getIntAttrOrZero(roomElement, STR_X);
		int y      = XMLBase.getIntAttrOrZero(roomElement, STR_Y);
		int width  = XMLBase.getIntAttrOrZero(roomElement, STR_WIDTH);
		int height = XMLBase.getIntAttrOrZero(roomElement, STR_HEIGHT);
		boolean isLit = XMLBase.getBooleanAttrOrTrue(roomElement, STR_IS_LIT);
		int id;
		try{
			id = Integer.parseInt(roomElement.getAttribute(STR_ID));
		}catch(NumberFormatException e){ 
			id = map.getNextID();
		}
		
		// create the Room object
		Room room = new Room(id, x, y, height, width, map);
		room.setIsLit(isLit);
		return room;
	}
	
	
	// -------------------------------------------------------------------------
	// cameras:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Position> getCameras(Element root, DataMap map) {
		List<Position> ret = new ArrayList<Position>();
		// get a node list of selected elements:
		NodeList rawList = root.getChildNodes();
		
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(
				node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_CAMERA)
			){
				Position camera = XMLLoader.getCamera((Element)node, map);
				ret.add(camera);
			}
		}
		
		return ret;
	}
	
	
	/**
	 * 
	 * @param cameraElement
	 * @param map
	 * @return
	 */
	private static Position getCamera(
			Element cameraElement,
			DataMap map
	) {
		// get the attributes:
		int id = XMLBase.getIntAttrOrZero(cameraElement, STR_ID);
		int x  = XMLBase.getIntAttrOrZero(cameraElement, STR_X);
		int y  = XMLBase.getIntAttrOrZero(cameraElement, STR_Y);
		boolean isActive = 
			XMLBase.getBooleanAttrOrFalse(cameraElement, STR_IS_ACTIVE);
		Room room;
		try{
			int roomId = 
				Integer.parseInt(cameraElement.getAttribute(STR_ROOM));
			room = map.getRoom(roomId);
		}catch(NumberFormatException e){
			room = null;
		}
		
		// create the object
		return new Camera(id, x, y, room, isActive, map);
	}
	
	
	// -------------------------------------------------------------------------
	// containers:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Position> getContainers(Element root, DataMap map) {
		List<Position> ret = new ArrayList<Position>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(
				node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_CONTAINER)
			){
				Position container = 
					XMLLoader.getContainer((Element)node, map);
				ret.add(container);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * @param containerElement
	 * @param map
	 * @return
	 */
	private static Position getContainer(
			Element containerElement,
			DataMap map
	) {		
		// get the attributes:
		int id     = XMLBase.getIntAttrOrZero(containerElement, STR_ID);
		int x      = XMLBase.getIntAttrOrZero(containerElement, STR_X);
		int y      = XMLBase.getIntAttrOrZero(containerElement, STR_Y);
		int roomId = XMLBase.getIntAttrOrZero(containerElement, STR_ROOM);
		int keyId  = XMLBase.getIntAttrOrZero(containerElement, STR_KEY);
		boolean isLocked = 
			XMLBase.getBooleanAttrOrFalse(containerElement, STR_IS_LOCKED);
		boolean isClosed = 
			XMLBase.getBooleanAttrOrTrue(containerElement, STR_IS_CLOSED);
		
		// create the object
		Room room = map.getRoom(roomId);
		Container container = null;
		if(keyId == 0) {
			container = new Container(id, x, y, room, isClosed, map);
		}else{
			container = new Container(id, x, y, room, isClosed, isLocked, keyId, map);
		}
		
		// fill the inventory:
		NodeList rawList = containerElement.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(
				node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_INVENTORY)
			){
				List<Item> items = XMLLoader.getItems((Element)node, map);
				map.addItems(items);
				container.addItems(items);
			}
		}
		
		return container;
	}
	
	
	// -------------------------------------------------------------------------
	// doors:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Position> getDoors(Element root, DataMap map) {
		List<Position> ret = new ArrayList<Position>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(
				node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_DOOR)
			){
				// get the element
				Element doorElement = (Element)node;
				Position door = XMLLoader.getDoor(doorElement, map);
				// add it to list
				ret.add(door);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * @param doorElement
	 * @param map
	 * @return
	 */
	private static Position getDoor(Element doorElement, DataMap map) {
		// get the attributes:
		int id       = XMLBase.getIntAttrOrZero(doorElement, STR_ID);
		int x        = XMLBase.getIntAttrOrZero(doorElement, STR_X);
		int y        = XMLBase.getIntAttrOrZero(doorElement, STR_Y);
		int fromRoom = XMLBase.getIntAttrOrZero(doorElement, STR_FROM_ROOM);
		int toRoom   = XMLBase.getIntAttrOrZero(doorElement, STR_TO_ROOM);
		int keyId    = XMLBase.getIntAttrOrZero(doorElement, STR_KEY);
		boolean isLocked = 
			XMLBase.getBooleanAttrOrFalse(doorElement, STR_IS_LOCKED);
		boolean isClosed = 
			XMLBase.getBooleanAttrOrTrue(doorElement, STR_IS_CLOSED);
		
		// create the object
		Room from = map.getRoom(fromRoom);
		Room to = map.getRoom(toRoom);
//		if(keyId == 0){
//			return new Door(id, x, y, from, to, isClosed, map);
//		}else{
			return new Door(id, x, y, from, to, isClosed, isLocked, keyId, map);
//		}
	}
	
	
	// -------------------------------------------------------------------------
	// floors:
	
	
	/**
	 * 
	 * It also sets onPath to true.
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Position> getFloors(Element root, DataMap map) {
		List<Position> ret = new ArrayList<Position>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(	node.getNodeType() == Node.ELEMENT_NODE && 
				node.getNodeName().equals(STR_FLOOR)
			){
				// get the element
				Element floorElement = (Element)node;
				// create the object
				Position floor = XMLLoader.getFloor(floorElement, map);
				ret.add(floor);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * It also sets onPath to true.
	 * 
	 * @param floorElement
	 * @param map
	 * @return
	 */
	private static Position getFloor(Element floorElement, DataMap map) {
		// get the attributes:
		int id = XMLBase.getIntAttrOrZero(floorElement, STR_ID);
		int x  = XMLBase.getIntAttrOrZero(floorElement, STR_X);
		int y  = XMLBase.getIntAttrOrZero(floorElement, STR_Y);
		Room room;
		try{
			int roomId = 
				Integer.parseInt(floorElement.getAttribute(STR_ROOM));
			room = map.getRoom(roomId);
		}catch(NumberFormatException e){
			room = null;
		}
				
		// create the object
		return new Floor(id, x, y, room, map);
	}
	
	
	// -------------------------------------------------------------------------
	// phones:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Position> getPhones(Element root, DataMap map) {
		List<Position> ret = new ArrayList<Position>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(	node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_PHONE)
			){
				// get the element
				Element phoneElement = (Element)node;
				// create the object
				Position phone = XMLLoader.getPhone(phoneElement, map);
				ret.add(phone);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * @param phoneElement
	 * @param map
	 * @return
	 */
	private static Position getPhone(Element phoneElement, DataMap map) {
		// get the attributes:
		int id = XMLBase.getIntAttrOrZero(phoneElement, STR_ID);
		int x  = XMLBase.getIntAttrOrZero(phoneElement, STR_X);
		int y  = XMLBase.getIntAttrOrZero(phoneElement, STR_Y);
		Boolean isRinging = 
			XMLBase.getBooleanAttrOrFalse(phoneElement, STR_IS_RINGING);
		Room room;
		try{
			int roomId = Integer.parseInt(phoneElement.getAttribute(STR_ROOM));
			room = map.getRoom(roomId);
		}catch(NumberFormatException e){
			room = null;
		}
		
		// create the object
		return new Phone(id, x, y, room, isRinging, map);
	}
	
	
	// -------------------------------------------------------------------------
	// switches:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Position> getSwitches(Element root, DataMap map) {
		List<Position> ret = new ArrayList<Position>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(	node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_SWITCH)
			){
				// get the element
				Element switchElement = (Element)node;
				// create the object
				Position position = XMLLoader.getSwitch(switchElement, map);
				ret.add(position);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static Position getSwitch(Element switchElement, DataMap map) {
		// get the attributes:
		int id = XMLBase.getIntAttrOrZero(switchElement, STR_ID);
		int x  = XMLBase.getIntAttrOrZero(switchElement, STR_X);
		int y  = XMLBase.getIntAttrOrZero(switchElement, STR_Y);
		int targetId = XMLBase.getIntAttrOrZero(switchElement, STR_TARGET);
		Room room;
		try{
			int roomId = Integer.parseInt(switchElement.getAttribute(STR_ROOM));
			room = map.getRoom(roomId);
		}catch(NumberFormatException e){
			room = null;
		}
		
		// create the object
		return new Switch(id, x, y, room, targetId, map);
	}
	
	
	// -------------------------------------------------------------------------
	// venders:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Position> getVenders(Element root, DataMap map) {
		List<Position> ret = new ArrayList<Position>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(	node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_VENDER)
			){
				// get the element
				Element venderElement = (Element)node;
				// create the object
				Position vender = XMLLoader.getVender(venderElement, map);
				ret.add(vender);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static Position getVender(Element venderElement, DataMap map) {
		// get the attributes:
		int id = XMLBase.getIntAttrOrZero(venderElement, STR_ID);
		int x  = XMLBase.getIntAttrOrZero(venderElement, STR_X);
		int y  = XMLBase.getIntAttrOrZero(venderElement, STR_Y);
		boolean	hasDropped = 
			XMLBase.getBooleanAttrOrFalse(venderElement, STR_HAS_DROPPED);
		Room room;
		try{
			int roomId = Integer.parseInt(venderElement.getAttribute(STR_ROOM));
			room = map.getRoom(roomId);
		}catch(NumberFormatException e){
			room = null;
		}
		
		// create the object
		return new Vender(id, x, y, room, hasDropped, map);
	}
	
	
	// -------------------------------------------------------------------------
	// burglar:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static Agent getBurglar(Element root, DataMap map) {
		// get a node list of selected elements
		NodeList nodes = root.getElementsByTagName(STR_BURGLAR);
		if(nodes == null || nodes.getLength() == 0)
			return null;
		
		// get the element
		Element burglarElement = (Element)nodes.item(0);
		
		// get the attributes:
		int id = 
			XMLBase.getIntAttrOrZero(burglarElement, STR_ID);
		int positionId = 
			XMLBase.getIntAttrOrZero(burglarElement, STR_POSITION);
		int aimId = -1;
		int collectId = -1;
		
		NodeList rawList = burglarElement.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			// fill the goals:
			if(	node.getNodeType() == Node.ELEMENT_NODE && 
				node.getNodeName().equals(STR_GOAL)
			){
				aimId = 
						XMLBase.getIntAttrOrZero((Element)node, STR_AIM);
				collectId = 
						XMLBase.getIntAttrOrZero((Element)node, STR_COLLECT);
			}
		}
		
		Position position = map.getPosition(positionId);
		Room aim = map.getRoom(aimId);
		
		// create the object:
		Burglar burglar = new Burglar(id, position, aim, collectId, map);
		
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			
			// fill the belief base object:
			if(	node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_BELIEFBASE)
			){
				Element mind = (Element)node;
				BeliefBase knowledge = burglar.getBeliefBase();
				knowledge.seenFromNear(XMLLoader.getPositions(mind, map));
			}
			
			// fill the inventory:
			if(	node.getNodeType() == Node.ELEMENT_NODE && 
				node.getNodeName().equals(STR_INVENTORY)
			){
				Element inventory = (Element)node;
				List<Item> items = XMLLoader.getItems(inventory, map);
				map.addItems(items);
				burglar.addItems(items);
			}
		}
		return burglar;
	}
	
	
	// -------------------------------------------------------------------------
	// guards:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Agent> getGuards(Element root, DataMap map) {
		List<Agent> ret = new ArrayList<Agent>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(	node.getNodeType() == Node.ELEMENT_NODE && 
				node.getNodeName().equals(STR_GUARD)
			){
				// get the element
				Element guardElement = (Element)node;
				// create the object
				Agent agent = XMLLoader.getGuard(guardElement, map);
				ret.add(agent);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * @param guardElement
	 * @param map
	 * @return
	 */
	private static Agent getGuard(Element guardElement, DataMap map) {
		// get the attributes:				
		int id = XMLBase.getIntAttrOrZero(guardElement, STR_ID);
		int positionId = XMLBase.getIntAttrOrZero(guardElement, STR_POSITION);
		Position position = map.getPosition(positionId);
		
		List<Integer> pathPositions = new LinkedList<Integer>();
		
		NodeList rawList = guardElement.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(	node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_GOAL)
			){
				// get the element
				Element pathElement = (Element)node;
				// create the object
				int routePositionId = 
					XMLBase.getIntAttrOrZero(pathElement, STR_ID);
				pathPositions.add(routePositionId);
			}
		}
		
		// create the object
		Guard guard = new Guard(id, position, pathPositions, map);
		
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			
			// fill the belief base object:
			if(	node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_BELIEFBASE)
			){
				Element mind = (Element)node;
				BeliefBase knowledge = guard.getBeliefBase();
				knowledge.seenFromNear(XMLLoader.getPositions(mind, map));
			}
			
			// fill the inventory:
			if(	node.getNodeType() == Node.ELEMENT_NODE && 
				node.getNodeName().equals(STR_INVENTORY)
			){
				Element inventory = (Element)node;
				List<Item> items = XMLLoader.getItems(inventory, map);
				map.addItems(items);
				guard.addItems(items);
			}
		}
		
		return guard;
	}
	
	
	// -------------------------------------------------------------------------
	// treasures:
	
	
	/**
	 * 
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Item> getTreasures(Element root, DataMap map) {
		List<Item> ret = new ArrayList<Item>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(	node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_TREASURE)
			){
				// get the element
				Element treasureElement = (Element)node;
				// create the object
				Item item = XMLLoader.getTreasure(treasureElement, map);
				ret.add(item);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static Item getTreasure(Element treasureElement, DataMap map) {
		// get the attributes:				
		int id = XMLBase.getIntAttrOrZero(treasureElement, STR_ID);
		
		// create the object:
		Item item = new Treasure(id, map);
		
		return item;
	}
	
	
	// -------------------------------------------------------------------------
	// keys:
	
	
	/**
	 * 
	 * @param root
	 * @param map
	 * @return
	 */
	private static List<Item> getKeys(Element root, DataMap map) {
		List<Item> ret = new ArrayList<Item>();
		// get a node list of selected elements
		NodeList rawList = root.getChildNodes();
		for(int i = 0; i < rawList.getLength(); i++){
			Node node = rawList.item(i);
			if(	node.getNodeType() == Node.ELEMENT_NODE &&
				node.getNodeName().equals(STR_KEY)
			){
				// get the element
				Element keyElement = (Element)node;
				// create the object
				Item key = XMLLoader.getKey(keyElement, map);
				// add it to list
				ret.add(key);
			}
		}
		return ret;
	}
	
	
	/**
	 * 
	 * @param keyElement
	 * @param map
	 * @return
	 */
	private static Item getKey(Element keyElement, DataMap map) {
		// get the attributes:				
		int id = XMLBase.getIntAttrOrZero(keyElement, STR_ID);
		
		// create the object:
		Item key = new Key(id, map);
		
		return key;
	}
	
	
}
